import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

class House {

    private final static ThreadLocal<Map<Integer, InnerNounPhrase>> NOUN = ThreadLocal.withInitial(() -> new HashMap<>() {
        {
            put(1, new InnerNounPhrase("Jack built", "", ""));
            put(2, new InnerNounPhrase("malt", "lay in", ""));
            put(3, new InnerNounPhrase("rat", "ate", ""));
            put(4, new InnerNounPhrase("cat", "killed", ""));
            put(5, new InnerNounPhrase("dog", "worried", ""));
            put(6, new InnerNounPhrase("cow", "tossed", "with the crumpled horn"));
            put(7, new InnerNounPhrase("maiden", "milked", "all forlorn"));
            put(8, new InnerNounPhrase("man", "kissed", "all tattered and torn"));
            put(9, new InnerNounPhrase("priest", "married", "all shaven and shorn"));
            put(10, new InnerNounPhrase("rooster", "woke", "that crowed in the morn"));
            put(11, new InnerNounPhrase("farmer", "kept", "sowing his corn"));
            put(12, new InnerNounPhrase("horse and the hound and the horn", "belonged to", ""));
        }
    });

    String verse(int inputNumber) {
        return String.format(
                "This is %s",
                this.f(inputNumber)
        );
    }

    private String f(int inputNumber) {
        if (inputNumber == 1) return "the house that Jack built.";

        return String.format(
                "%s%s",
                House.NOUN.get().get(inputNumber).getPhrase(),
                f(inputNumber - 1)
        );
    }

    String sing() {
        return this.verses(1, 12);
    }

    String verses(int startVerse, int endVerse) {
        StringBuilder result = new StringBuilder();
        IntStream
                .range(startVerse, endVerse + 1)
                .forEach(
                        verse -> result
                                .append(this.verse(verse))
                                .append("\n\n")
                );

        return result.substring(0, result.length() - 2);
    }

    static class InnerNounPhrase {
        private final String noun;
        private final String preModifier;
        private final String determinative;

        InnerNounPhrase(final String noun,
                        final String preModifier,
                        final String determinative) {

            this.noun = noun;
            this.preModifier = preModifier;
            this.determinative = determinative;
        }

        String getPhrase() {
            return String.format(
                    "the %s%s\nthat %s ",
                    this.noun, this.determinative.equals("") ? "" : " " + this.determinative,
                    this.preModifier
            );
        }
    }
}